package org.ecloud.oauth.client.filter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.apache.http.Header;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.ecloud.common.constants.StateEnum;
import org.ecloud.core.entity.APIResult;
import org.ecloud.oauth.client.config.AuthorizationConfig;
import org.ecloud.oauth.client.service.ContextOrgService;
import org.ecloud.oauth.client.service.ContextPositionService;
import org.ecloud.oauth.client.service.ContextUserService;
import org.ecloud.oauth.client.service.TokenService;
import org.ecloud.oauth.client.utils.RequestUtil;
import org.ecloud.oauth.constants.ParameterKey;
import org.ecloud.utils.HttpClientUtil;
import org.ecloud.utils.JacksonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;

public abstract class AbstractFilter implements Filter {

	protected static final String REQUEST_TYPE_HTTPCLIENT = "httpclient";
	protected static final String REQUEST_TYPE_FEIGNCLIENT = "feignclient";
	protected Logger logger = LoggerFactory.getLogger(getClass());
	@Autowired
	protected AuthorizationConfig authorizationConfig;
	
	@Autowired
	private TokenService tokenService;
	@Autowired
	private ContextUserService contextUserService;
	@Autowired
	private ContextOrgService contextOrgService;
	@Autowired
	private ContextPositionService contextPositionService;
	
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
	}

	@Override
	public void destroy() {
	}
	
	@SuppressWarnings("unchecked")
	protected APIResult<String> verify(String accessToken){
		APIResult<String> tokenResult = null;
		
		if(REQUEST_TYPE_FEIGNCLIENT.equalsIgnoreCase(authorizationConfig.getRequestType())){
			tokenResult = tokenService.verify(accessToken);
		} else if(REQUEST_TYPE_HTTPCLIENT.equalsIgnoreCase(authorizationConfig.getRequestType())){
			logger.debug("accessTokenVerifyUrl =====> {}", authorizationConfig.getAccessTokenVerifyUrlFull());
			String responseData = null;
			if(HttpMethod.GET.name().equalsIgnoreCase(authorizationConfig.getRequestMethod())){
				Map<String, String> paramMap = new HashMap<>();
				paramMap.put(ParameterKey.PARAMETER_ACCESS_TOKEN, accessToken);
				responseData = HttpClientUtil.doGet(authorizationConfig.getAccessTokenVerifyUrlFull(), paramMap);
			} else if(HttpMethod.POST.name().equalsIgnoreCase(authorizationConfig.getRequestMethod())){
				List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
				nameValuePairs.add(new BasicNameValuePair(ParameterKey.PARAMETER_ACCESS_TOKEN, accessToken));
				responseData = HttpClientUtil.doPost(authorizationConfig.getAccessTokenVerifyUrlFull(), nameValuePairs);
			} else {
				throw new RuntimeException("请求方法不支持");
			}
			
			tokenResult = JacksonUtil.getDTO(responseData, APIResult.class);
		} else {
			throw new RuntimeException("请求方式不支持");
		}
		
		return tokenResult;
	}
	
	/**
	 * 构造请求header
	 *
	 * @param accessToken
	 * @return 
	 */
	protected Map<String, Object> getTokenHeaderMap(String accessToken){
		Map<String, Object> map = new HashMap<>();
		map.put(ParameterKey.HEADER_AUTHORIZATION, accessToken);
		map.put(ParameterKey.HEADER_CONTEXT, accessToken);
		return map;
	}
	
	/**
	 * 构造请求header
	 *
	 * @param accessToken
	 * @return 
	 */
	protected Header[] getTokenHeader(String accessToken){
		Header[] headers = new Header[]{
				new BasicHeader(ParameterKey.HEADER_CONTEXT, accessToken), 
				new BasicHeader(ParameterKey.HEADER_AUTHORIZATION, accessToken)};
		return headers;
	}
	
	/**
	 * 设置上下文数据
	 *
	 * @param accessToken
	 * @param username 
	 */
	protected void setContext(HttpServletRequest request, String accessToken, String username){
		setContextIp(request);
		setContextAccessToken(accessToken);
		setContextUser(accessToken, username);
		setContextOrg(accessToken, username);
		setContextPosition(accessToken, username);
	}

	/**
	 * 设置ip上下文
	 * 
	 */
	protected void setContextIp(HttpServletRequest request){
		String ip = RequestUtil.getIpAddr(request);
		logger.debug("current ip {}", ip);
		//ContextUtil.setCurrentUserIp(ip);
	}
	
	/**
	 * 设置令牌上下文数据
	 *
	 * @param accessToken 
	 */
	protected void setContextAccessToken(String accessToken){
		logger.debug("current access token {}", accessToken);
		// 保存本地线程数据
		//ContextUtil.setCurrentAccessToken(accessToken);
	}
	
	/**
	 * 设置用户上下文数据
	 *
	 * @param accessToken
	 * @param username 
	 */
	@SuppressWarnings("unchecked")
	protected void setContextUser(String accessToken, String username){
		APIResult<String> result = null;
		if(REQUEST_TYPE_FEIGNCLIENT.equalsIgnoreCase(authorizationConfig.getRequestType())){
			result = contextUserService.context(accessToken, accessToken, username);
		} else if(REQUEST_TYPE_HTTPCLIENT.equalsIgnoreCase(authorizationConfig.getRequestType())){
			logger.debug("contextUserUrlUrl =====> {}", authorizationConfig.getContextUserUrlFull());
			String responseData = null;
			if(HttpMethod.GET.name().equalsIgnoreCase(authorizationConfig.getRequestMethod())){
				Map<String, String> paramMap = new HashMap<>();
				paramMap.put("username", username);
				responseData = HttpClientUtil.doGet(authorizationConfig.getContextUserUrlFull(), paramMap, getTokenHeader(accessToken));
			} else if(HttpMethod.POST.name().equalsIgnoreCase(authorizationConfig.getRequestMethod())){
				List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
				nameValuePairs.add(new BasicNameValuePair(ParameterKey.PARAMETER_USERNAME, username));
				responseData = HttpClientUtil.doPost(authorizationConfig.getContextUserUrlFull(), nameValuePairs, getTokenHeader(accessToken));
			} else {
				throw new RuntimeException("请求方法不支持");
			}
			result = JacksonUtil.getDTO(responseData, APIResult.class);
		} else {
			throw new RuntimeException("请求方式不支持");
		}
		
		if(StateEnum.SUCCESS.getCode() == result.getCode()){
			logger.debug("current user {}", result.getData());
			//ContextUtil.setCurrentUser(user);
		} else {
			throw new RuntimeException(result.getCause());
		}
	}
	
	/**
	 * 设置部门上下文数据
	 *
	 * @param accessToken
	 * @param username 
	 */
	@SuppressWarnings("unchecked")
	protected void setContextOrg(String accessToken, String username){
		APIResult<String> result = null;
		if(REQUEST_TYPE_FEIGNCLIENT.equalsIgnoreCase(authorizationConfig.getRequestType())){
			result = contextOrgService.context(accessToken, accessToken, username);
		} else if(REQUEST_TYPE_HTTPCLIENT.equalsIgnoreCase(authorizationConfig.getRequestType())){
			logger.debug("contextOrgUrlUrl =====> {}", authorizationConfig.getContextOrgUrlFull());
			String responseData = null;
			if(HttpMethod.GET.name().equalsIgnoreCase(authorizationConfig.getRequestMethod())){
				Map<String, String> paramMap = new HashMap<>();
				paramMap.put("username", username);
				responseData = HttpClientUtil.doGet(authorizationConfig.getContextOrgUrlFull(), paramMap, getTokenHeader(accessToken));
			} else if(HttpMethod.POST.name().equalsIgnoreCase(authorizationConfig.getRequestMethod())){
				List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
				nameValuePairs.add(new BasicNameValuePair(ParameterKey.PARAMETER_USERNAME, username));
				responseData = HttpClientUtil.doPost(authorizationConfig.getContextOrgUrlFull(), nameValuePairs, getTokenHeader(accessToken));
			} else {
				throw new RuntimeException("请求方法不支持");
			}
			result = JacksonUtil.getDTO(responseData, APIResult.class);
		} else {
			throw new RuntimeException("请求方式不支持");
		}
		
		if(StateEnum.SUCCESS.getCode() == result.getCode()){
			logger.debug("current org {}", result.getData());
			//ContextUtil.setCurrentOrg(org);
		}
	}
	
	/**
	 * 设置岗位上下文数据
	 *
	 * @param accessToken
	 * @param username 
	 */
	@SuppressWarnings("unchecked")
	protected void setContextPosition(String accessToken, String username){
		APIResult<String> result = null;
		
		if(REQUEST_TYPE_FEIGNCLIENT.equalsIgnoreCase(authorizationConfig.getRequestType())){
			result = contextPositionService.context(accessToken, accessToken, username);
		} else if(REQUEST_TYPE_HTTPCLIENT.equalsIgnoreCase(authorizationConfig.getRequestType())){
			logger.debug("contextPositionUrlUrl =====> {}", authorizationConfig.getContextPositionUrlFull());
			String responseData = null;
			if(HttpMethod.GET.name().equalsIgnoreCase(authorizationConfig.getRequestMethod())){
				Map<String, String> paramMap = new HashMap<>();
				paramMap.put("username", username);
				responseData = HttpClientUtil.doGet(authorizationConfig.getContextPositionUrlFull(), paramMap, getTokenHeader(accessToken));
			} else if(HttpMethod.POST.name().equalsIgnoreCase(authorizationConfig.getRequestMethod())){
				List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
				nameValuePairs.add(new BasicNameValuePair(ParameterKey.PARAMETER_USERNAME, username));
				responseData = HttpClientUtil.doPost(authorizationConfig.getContextPositionUrlFull(), nameValuePairs, getTokenHeader(accessToken));
			} else {
				throw new RuntimeException("请求方法不支持");
			}
			
			result = JacksonUtil.getDTO(responseData, APIResult.class);
		} else {
			throw new RuntimeException("请求方式不支持");
		}
		
		if(StateEnum.SUCCESS.getCode() == result.getCode()){
			logger.debug("current position {}", result.getData());
			//ContextUtil.setCurrentPosition(position);
		}
	}
	
}
